<!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML>
<HEAD>
<TITLE>ArmBob's datatypes</TITLE>
<LINK REL=STYLESHEET HREF="style.css" TYPE="text/css">
</HEAD>
<BODY style="margin: 4em;">
<H2>ArmBob's datatypes</H2>

All values in ArmBob programs have one of the following types.
<UL>
<LI> <A HREF="#nil">NIL</A>
<LI> <A HREF="#integer">INTEGER</A>
<LI> <A HREF="#real">REAL</A>
<LI> <A HREF="#string">STRING</A>
<LI> <A HREF="#bytecode">BYTECODE</A>
<LI> <A HREF="#code">CODE</A>
<LI> <A HREF="#iostream">IOSTREAM</A>
<LI> <A HREF="#vector">VECTOR</A>
<LI> <A HREF="#object">OBJECT</A>
</UL>
These names are predefined as synonyms for the numerical codes
returned by the function <A HREF="Glossary#typeof"> <CODE>typeof</CODE></A>.
The values of these numerical codes are not important, except that NIL has
the value 0, and all other types have nonzero code.
<P>
Typing in ArmBob is implicit. Values carry their type around with them
and typechecking occurs at run time. There are no type declarations.
That is to say, types attach to values, not to variables or
expressions (apart from literal expressions).
<HR>
<H3><A NAME="nil">NIL</A></H3>
This type has only one value: <CODE>nil</CODE>. It is the
default value for unassigned variables, and for functions with
no <CODE>return</CODE> statement. As a conditional,
<CODE>nil</CODE> counts as FALSE.

<H3><A NAME="integer">INTEGER</A></H3>
Integers must be in the range from -2147483648 to 2147483647. They
may also be used in hexadecimal form, with a &#39;&amp;&#39; as 
prefix, with lower case a,b,c,d,e,f denoting 10,11,12,13,14,15, 
in the range from &amp;00000000 to &amp;ffffffff. 
Characters are simply integers in the range 0-255. Single 
characters are enclosed in single forward quote characters 
<CODE>(&#39;)</CODE>.  So <CODE>&#39;A&#39;</CODE>
also denotes the integer 65, for example. 
The character <CODE>&#39;\&#39;</CODE> is used as an escape character,
with <CODE>&#39;\n&#39;, &#39;\t&#39;, &#39;\0&#39;</CODE> denoting the
newline, tab and null characters. 

In conditional expressions, any nonzero integer is taken to represent 
truth, and zero or nil as falsity. TRUE is a synonym for 1 and FALSE 
is a synonym for 0. 

It is also possible to use integers as addresses.

<H3><A NAME="real">REAL</A></H3>
Single precision floating point numbers are characterised by the 
presence of a decimal point. Thus <CODE>x = 0;</CODE> will make
<CODE>x</CODE> an integer, but <CODE>x = 0.0;</CODE> will make
<CODE>x</CODE> a real. Reals can be multiplied or divided by
either reals or integers and the result is a real. So an integer can
be converted to a real by multiplying it by 1.0. 
You may not add or subtract a real with an integer. 

<H3><A NAME="string">STRING</A></H3>
Strings are arrays of bytes. They can be created either by a command
of the form <PRE>
        string_name = newstring(size); </PRE>
which creates a string of ASCII nulls, of size <CODE> size </CODE>, 
or by an assignment to a literal string. Literal strings are enclosed in double quotes
(&quot;) and may not contain the double-quote character.
The component characters of a string <CODE>s</CODE> are
<PRE>
              s[0], s[1], ........ s[sizeof(s)-1]
</PRE>
As in BASIC, strings may be concatenated using the operators
<CODE>+</CODE> and <CODE>+=</CODE>. So <CODE>s += t</CODE>
is equivalent to <CODE>s = s + t</CODE>. In fact string handling
in ArmBob resembles BASIC rather than C. The operator <CODE>+</CODE>
can also be used to add characters to strings. This operator 
associates to the left, so that
<PRE>
            33+33+&quot;&quot;
</PRE>
is the 1-element string <CODE>&quot;B&quot;</CODE>, while
<PRE>
            &quot;&quot;+33+33
</PRE>
is the 2-element string <CODE>&quot;!!&quot;</CODE>.
The function <CODE>val</CODE> will convert as much of a
string into a number as it can. So 
<CODE>val(&quot; +10x&quot;)</CODE> and
<CODE>val(&quot;&amp;a&quot;)</CODE> will both return 10.
The comparison operators work with strings as well as numbers,
and strings may be used after <CODE>case</CODE> in
<CODE>switch</CODE> structures.

<H3><A NAME="bytecode">BYTECODE</A></H3>
This is the type of user defined functions and methods.
These can only appear at the top level of a program.
Every program must have just one function called <CODE>main</CODE>
defined. This determines the entry point for the program.
Functions can be the values of variables. Note that the parenthesized
list of formal parameters following the function name in a function
definition is not part of the function name itself. Functions can be 
returned as values of functions. E.g. <PRE>
      add(x,y) { return x+y; }
      mul(x,y) { return x*y; }
      main()
      { print(&quot;+/*?&quot;);
        print(((input() == &quot;*&quot;)?mul:add)(2,100),&quot;\n&quot;); }
</PRE>

<H3><A NAME="code">CODE</A></H3>
This is the type of built-in functions. Although built-in and user
defined functions are represented differently internally, and have
different types, in all other respects they behave the same way.

<H3><A NAME="iostream">IOSTREAM</A></H3>
The following function, to type out the contents of a file, illustrates
how iostreams are opened and closed.<PRE>

      typefile(filename)
      {
          local fp,c;
          if (fp = fopen(filename,&quot;r&quot;))
          {
              while ((c = getc(fp)) != EOF)
                  putc(c,stdout);
              fclose(fp);
          }
      }
</PRE>The iostreams
<A HREF="Glossary#stderr"> <CODE>stderr</CODE> </A>,
<A HREF="Glossary#stdin"> <CODE>stdin</CODE> </A>,
<A HREF="Glossary#stdout"> <CODE>stdout</CODE> </A>,
are built in. The following iostream handling functions are built in:
<A HREF="Glossary#fclose"> <CODE>fclose</CODE> </A>,
<A HREF="Glossary#fopen"> <CODE>fopen</CODE> </A>,
<A HREF="Glossary#getc"> <CODE>getc</CODE> </A>,
<A HREF="Glossary#putc"> <CODE>putc</CODE> </A>.
The expression <CODE>fp &lt;&lt; s</CODE> will output
the string <CODE>s</CODE> to iostream <CODE>fp</CODE>.
The value of this expression is <CODE>fp</CODE>, and
<CODE>&lt;&lt;</CODE> associates to the left, so that
<PRE>
           fp &lt;&lt; s1 &lt;&lt; s2 .....
</PRE>
is equivalent to
<PRE>
           fp &lt;&lt; (s1 + s2 + ...... )
</PRE>

<H3><A NAME="vector">VECTOR</A></H3>
Vectors are arrays of fixed size. Their components can have any type.
In fact a vector can be one of its own components. Vectors allow one 
to construct complex datatypes.
They can be created by statements of the form
<PRE>
           v = newvector(size);
</PRE>
which creates a new vector with <CODE>size</CODE> components which are
all <CODE>nil</CODE>. The components are
<PRE>
            v[0], .... , v[size-1]
</PRE>
Alternatively, the expression
<PRE>
           vector { <VAR>expr1</VAR>; ...... <VAR>exprn</VAR>; }
</PRE>
returns a new vector with components <VAR>expr1 ... exprn</VAR>. 
There must be at least one component and not more than 255 for 
this construction. Vectors have only one index. To define
matrices we could define
<PRE>
   newmatrix(m,n)
   {
    local matrix,i;
    matrix = newvector(m);
    for(i=0;i&lt;m;i++)
       matrix[i] = newvector(n);
    return matrix;
   }
</PRE>
and <CODE>matrix[i][j]</CODE> will be the element in the
<CODE>i</CODE>-th row and <CODE>j</CODE>-th column.
This has the advantage that the <CODE>i</CODE>-th row is
<CODE>matrix[i]</CODE>. When a vector is first created its
components all have the value <CODE>nil</CODE>. We can replace
the numerical indices by names using the 
<CODE><A HREF="Glossary#enum">enum</A></CODE>
function. E.g.
<PRE>
          _3_vector = enum { x, y, z };
          v  = newvector(_3_vector);
          v[x] = v[y] = v[z] = 0.0;
</PRE>

<H3><A NAME="object">OBJECT</A></H3>
Following the conventions of C++, for every class one must define a
function with the same name as the class, to be used for creating
instance objects of the class. This function must exit with the
statement <CODE>return this;</CODE>. E.g.
<PRE>
      class person {age; name;}

      person::person(a,n)   // for creating new persons
      { age = a; name = n; return this;}

      person::has_age()     // for getting the age of a person
      { return age; }

      person::called()      // for getting the name of a person
      { return name; }

      person::older(y)      // for making a person age
      { age += y; }

      person::tell_age()    // tell how old someone is
      {
       stdout &lt;&lt; this->called()
              &lt;&lt; " is "
              &lt;&lt; this->has_age()
              &lt;&lt; " years old.\n" ;
       }

      main()
      {
       Fred = new person(30,"Fred");  // Fred is born 30 years old
       Fred->tell_age();
       Fred->older(10);               // he ages 10 years     
       Fred->tell_age();
      }
</PRE>
This example demonstrates the use of the all-important operators
<A HREF="Glossary#colon2"> <CODE>::</CODE> </A> and
<A HREF="Glossary#arrow"> <CODE>-&gt;</CODE> </A> for defining
and using methods, and the keyword
<A HREF="Glossary#new"> <CODE>new</CODE> </A> for creating
instance objects.
<P>
<HR>
<A HREF="index.html">Back to the index</A>
</BODY>
</HTML>
